/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "can.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* 定义线程栈空间 */
static rt_uint8_t os_task_5ms_stack[512];
static rt_uint8_t os_task_10ms_stack[512];
static rt_uint8_t os_task_100ms_stack[512];
static rt_uint8_t os_task_1000ms_stack[512];

/* 定义线程控制块 */
static struct rt_thread os_task_5ms_thread_TCB;
static struct rt_thread os_task_10ms_thread_TCB;
static struct rt_thread os_task_100ms_thread_TCB;
static struct rt_thread os_task_1000ms_thread_TCB;

/* 定义任务周期激活信号量 */
static struct rt_semaphore os_task_5ms_active_sem;
static struct rt_semaphore os_task_10ms_active_sem;
static struct rt_semaphore os_task_100ms_active_sem;
static struct rt_semaphore os_task_1000ms_active_sem;

/* 定义任务周期定时器 */
static struct rt_timer os_timer_5ms;
static struct rt_timer os_timer_10ms;
static struct rt_timer os_timer_100ms;
static struct rt_timer os_timer_1000ms;

/* 定义串口接收队列 */
#define MAX_MSGS    64
struct rt_messagequeue uart1_rx_queue;
rt_uint8_t msg_pool[MAX_MSGS];

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* 定义线程入口函数 */
static void OsTask_5ms_thread_entry(void* parameter);
static void OsTask_10ms_thread_entry(void* parameter);
static void OsTask_100ms_thread_entry(void* parameter);
static void OsTask_1000ms_thread_entry(void* parameter);

/* 定义定时器超时函数 */
static void OsTimer_5ms_timeout(void* parameter);
static void OsTimer_10ms_timeout(void* parameter);
static void OsTimer_100ms_timeout(void* parameter);
static void OsTimer_1000ms_timeout(void* parameter);

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */
  rt_err_t result = -RT_ERROR;

  result = rt_mq_init(&uart1_rx_queue, "uart1_rx_queue", msg_pool, 1, MAX_MSGS, RT_IPC_FLAG_FIFO);
  if (RT_EOK != result)
  {
    rt_kprintf("Failed to initialize uart1_rx_queue! Error code: %d\n", result);
    return -1;
  }

  /* 初始化线程 */
  result = rt_thread_init(
    &os_task_5ms_thread_TCB,      /* 线程控制块 */
    "os_task_5ms",                /* 线程名称 */
    OsTask_5ms_thread_entry,      /* 线程入口函数 */
    RT_NULL,                      /* 线程入口函数参数 */
    os_task_5ms_stack,            /* 线程栈起始地址 */
    sizeof(os_task_5ms_stack),    /* 线程栈大小 */
    0,                            /* 线程栈优先级 */
    5                             /* 线程时间片 */
  );
  if (RT_EOK != result)
  {
    rt_kprintf("Failed to initialize os_task_5ms_thread! Error code: %d\n", result);
    return -1;
  }

  result = rt_thread_init(
    &os_task_10ms_thread_TCB,     /* 线程控制块 */
    "os_task_10ms",               /* 线程名称 */
    OsTask_10ms_thread_entry,     /* 线程入口函数 */
    RT_NULL,                      /* 线程入口函数参数 */
    os_task_10ms_stack,           /* 线程栈起始地址 */
    sizeof(os_task_10ms_stack),   /* 线程栈大小 */
    1,                            /* 线程栈优先级 */
    5                             /* 线程时间片 */
  );
  if (RT_EOK != result)
  {
    rt_kprintf("Failed to initialize os_task_10ms_thread! Error code: %d\n", result);
    return -1;
  }

  result = rt_thread_init(
    &os_task_100ms_thread_TCB,    /* 线程控制块 */
    "os_task_100ms",              /* 线程名称 */
    OsTask_100ms_thread_entry,    /* 线程入口函数 */
    RT_NULL,                      /* 线程入口函数参数 */
    os_task_100ms_stack,          /* 线程栈起始地址 */
    sizeof(os_task_100ms_stack),  /* 线程栈大小 */
    2,                            /* 线程栈优先级 */
    5                             /* 线程时间片 */
  );
  if (RT_EOK != result)
  {
    rt_kprintf("Failed to initialize os_task_100ms_thread! Error code: %d\n", result);
    return -1;
  }

  result = rt_thread_init(
    &os_task_1000ms_thread_TCB,   /* 线程控制块 */
    "os_task_1000ms",             /* 线程名称 */
    OsTask_1000ms_thread_entry,   /* 线程入口函数 */
    RT_NULL,                      /* 线程入口函数参数 */
    os_task_1000ms_stack,         /* 线程栈起始地址 */
    sizeof(os_task_1000ms_stack), /* 线程栈大小 */
    3,                            /* 线程栈优先级 */
    5                             /* 线程时间片 */
  );
  if (RT_EOK != result)
  {
    rt_kprintf("Failed to initialize os_task_1000ms_thread! Error code: %d\n", result);
    return -1;
  }

  /* 初始化信号量 */
  result = rt_sem_init(
                &os_task_5ms_active_sem,      /* 信号量控制块 */
                "os_task_5ms_active",         /* 信号量名称 */
                0,                            /* 信号量初值 */
                RT_IPC_FLAG_PRIO              /* 优先级等待方式 */
  );
  if (RT_EOK != result)
  {
    rt_kprintf("Failed to initialize os_task_5ms_active! Error code: %d\n", result);
    return -1;
  }

  result = rt_sem_init(
                &os_task_10ms_active_sem,     /* 信号量控制块 */
                "os_task_10ms_active",        /* 信号量名称 */
                0,                            /* 信号量初值 */
                RT_IPC_FLAG_PRIO              /* 优先级等待方式 */
  );
  if (RT_EOK != result)
  {
    rt_kprintf("Failed to initialize os_task_10ms_active! Error code: %d\n", result);
    return -1;
  }

  result = rt_sem_init(
                &os_task_100ms_active_sem,    /* 信号量控制块 */
                "os_task_100ms_active",       /* 信号量名称 */
                0,                            /* 信号量初值 */
                RT_IPC_FLAG_PRIO              /* 优先级等待方式 */
  );
  if (RT_EOK != result)
  {
    rt_kprintf("Failed to initialize os_task_100ms_active! Error code: %d\n", result);
    return -1;
  }

  result = rt_sem_init(
                &os_task_1000ms_active_sem,   /* 信号量控制块 */
                "os_task_1000ms_active",      /* 信号量名称 */
                0,                            /* 信号量初值 */
                RT_IPC_FLAG_PRIO              /* 优先级等待方式 */
  );
  if (RT_EOK != result)
  {
    rt_kprintf("Failed to initialize os_task_1000ms_active! Error code: %d\n", result);
    return -1;
  }


  /* 初始化定时器 */
  rt_timer_init(  &os_timer_5ms,            /* 定时器控制块 */
                  "os_timer_5ms",           /* 定时器名称 */
                  OsTimer_5ms_timeout,      /* 定时器超时函数 */
                  RT_NULL,                  /* 定时器超时函数入口参数 */
                  5,                        /* 超时时间 */
                  RT_TIMER_FLAG_PERIODIC);  /* 周期定时器 */

  rt_timer_init(  &os_timer_10ms,           /* 定时器控制块 */
                  "os_timer_10ms",          /* 定时器名称 */
                  OsTimer_10ms_timeout,     /* 定时器超时函数 */
                  RT_NULL,                  /* 定时器超时函数入口参数 */
                  10,                       /* 超时时间 */
                  RT_TIMER_FLAG_PERIODIC);  /* 周期定时器 */

  rt_timer_init(  &os_timer_100ms,          /* 定时器控制块 */
                  "os_timer_100ms",         /* 定时器名称 */
                  OsTimer_100ms_timeout,    /* 定时器超时函数 */
                  RT_NULL,                  /* 定时器超时函数入口参数 */
                  100,                      /* 超时时间 */
                  RT_TIMER_FLAG_PERIODIC);  /* 周期定时器 */

  rt_timer_init(  &os_timer_1000ms,         /* 定时器控制块 */
                  "os_timer_1000ms",        /* 定时器名称 */
                  OsTimer_1000ms_timeout,   /* 定时器超时函数 */
                  RT_NULL,                  /* 定时器超时函数入口参数 */
                  1000,                     /* 超时时间 */
                  RT_TIMER_FLAG_PERIODIC);  /* 周期定时器 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  // HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  // SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CAN1_Init();
  Canif_Init();
  CanTP_Init();
  /* USER CODE BEGIN 2 */

  /* 启动线程，开启调度 */
  if (RT_EOK != rt_thread_startup(&os_task_5ms_thread_TCB))
  {
    rt_kprintf("Failed to startup os_task_5ms_thread! Error code: %d\n", result);
    return -1;
  }

  if (RT_EOK != rt_thread_startup(&os_task_10ms_thread_TCB))
  {
    rt_kprintf("Failed to startup os_task_10ms_thread! Error code: %d\n", result);
    return -1;
  }

  if (RT_EOK != rt_thread_startup(&os_task_100ms_thread_TCB))
  {
    rt_kprintf("Failed to startup os_task_100ms_thread! Error code: %d\n", result);
    return -1;
  }

  if (RT_EOK != rt_thread_startup(&os_task_1000ms_thread_TCB))
  {
    rt_kprintf("Failed to startup os_task_1000ms_thread! Error code: %d\n", result);
    return -1;
  }

  /* 启动定时器 */
  rt_timer_start(&os_timer_5ms);
  rt_timer_start(&os_timer_10ms);
  rt_timer_start(&os_timer_100ms);
  rt_timer_start(&os_timer_1000ms);

  return 0;
  /* USER CODE END 2 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

static void OsTask_5ms_thread_entry(void* parameter)
{
	while (1)
	{
    if (RT_EOK == rt_sem_take(&os_task_5ms_active_sem, RT_WAITING_FOREVER))
    {
    }
	}
}

static void OsTask_10ms_thread_entry(void* parameter)
{
	while (1)
	{
    /* 等待信号量激活任务 */
    if (RT_EOK == rt_sem_take(&os_task_10ms_active_sem, RT_WAITING_FOREVER))
    {
      Canif_MainFunction_Tx();
      Canif_MainFunction_Rx();
      Cantp_MainFunction();
    }
	}
}

static void OsTask_100ms_thread_entry(void* parameter)
{
	while (1)
	{
    rt_uint32_t id = 0;
    rt_uint8_t data[8] = {0};
    rt_uint8_t dlc = 0;

    /* 等待信号量激活任务 */
    if (RT_EOK == rt_sem_take(&os_task_100ms_active_sem, RT_WAITING_FOREVER))
    {
      /* 接收通信报文 */
      while (RT_TRUE == Canif_Com_receive_frame(&id, data, &dlc))
      {
        /* 外发通信报文 */
        Canif_Com_send_frame(0x100, data, dlc);

        /* 串口打印接收通信报文 */
        rt_kprintf("Rx ID: %X\t", id);
        rt_kprintf("DLC: %X\t", dlc);
        rt_kprintf("MSG: ");
        for (rt_uint8_t i = 0; i < dlc; i++)
        {
            rt_kprintf("%02X ", data[i]);
        }
        rt_kprintf("\r\n");
      }

      HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10);     /* LED0对应引脚PF10拉高，灭，等同于LED0(1) */
    }
	}
}

static void OsTask_1000ms_thread_entry(void* parameter)
{
	while (1)
	{
    /* 等待信号量激活任务 */
    if (RT_EOK == rt_sem_take(&os_task_1000ms_active_sem, RT_WAITING_FOREVER))
    {
		  HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_9);    /* LED0对应引脚PF9拉高，灭，等同于LED0(1) */
    }
	}
}

static void OsTimer_5ms_timeout(void* parameter)
{
  /* 释放信号量 */
  rt_sem_release(&os_task_5ms_active_sem);
}

static void OsTimer_10ms_timeout(void* parameter)
{
  /* 释放信号量 */
  rt_sem_release(&os_task_10ms_active_sem);
}

static void OsTimer_100ms_timeout(void* parameter)
{
  /* 释放信号量 */
  rt_sem_release(&os_task_100ms_active_sem);
}

static void OsTimer_1000ms_timeout(void* parameter)
{
  /* 释放信号量 */
  rt_sem_release(&os_task_1000ms_active_sem);
}

/* USER CODE END 4 */

/**
  * @brief  Period elapsed callback in non blocking mode
  * @note   This function is called  when TIM1 interrupt took place, inside
  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
  * a global variable "uwTick" used as application time base.
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM1) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */

  /* USER CODE END Callback 1 */
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
